package com.tianyadu.mmall.controller;

import com.tianyadu.mmall.controller.async.DeferredResultHolder;
import com.tianyadu.mmall.controller.async.MockQueue;
import com.tianyadu.mmall.core.utils.KeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.concurrent.Callable;

/**
 * 模拟异步处理请求
 *
 * @author xueyj
 * @date 2019-09-29 14:02
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class AsyncController {

    /**
     * 注入消息队列信息
     */
    @Autowired
    private MockQueue mockQueue;
    /**
     * 注入请求结果信息
     */
    @Autowired
    private DeferredResultHolder deferredResultHolder;

    /**
     * 同步处理订单信息
     *
     * @return java.lang.String
     * @author xueyj
     * @date 2019/9/29-14:14
     */
    @RequestMapping("/synchroCreateOrder")
    public String synchroCreateOrder() throws Exception {
        log.info("主线程调用开始");
        Thread.sleep(1000);
        log.info("主线程调用结束");
        return "success";
    }

    /**
     * 使用Callable副线程处理订单信息（依赖于主线程）
     * 此方法调用，子线程的调用必须由父线程发起，代码运行包含在主线程中
     *
     * @return java.util.concurrent.Callable<java.lang.String>
     * @author xueyj
     * @date 2019/9/29-14:14
     */
    @RequestMapping("/createOrderByCallable")
    public Callable<String> createOrderByCallable() throws Exception {
        log.info("主线程调用开始");
        Callable<String> result = new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("副线程调用开始");
                Thread.sleep(1000);
                log.info("副线程调用结束");
                return "success";
            }
        };
        log.info("主线程调用结束");
        return result;
    }

    /**
     * 使用DeferredResult异步处理订单信息（脱离当前主线程）
     *
     * @return org.springframework.web.context.request.async.DeferredResult<java.lang.String>
     * @author xueyj
     * @date 2019/9/29-14:14
     */
    @RequestMapping("/createOrderByDeferredResult")
    public DeferredResult<String> createOrderByDeferredResult() throws Exception {
        log.info("主线程调用开始");

        // 生成订单号信息
        String orderNumber = KeyUtil.genUniqueKey();
        //  将订单信息存放至消息队列中
        mockQueue.setPlaceOrder(orderNumber);
        //  传递订单信息至DeferredResult
        DeferredResult<String> result = new DeferredResult<>();
        deferredResultHolder.getMap().put(orderNumber, result);
        return result;
    }
}